/**
 * Copyright (C) 2009-2012, KingHool.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses.
 */
package com.kinghool.smodel.io.xml;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.jdom.Document;
import org.jdom.Element;

import com.kinghool.ebos.commons.exception.ErrorCodeRuntimeException;
import com.kinghool.smodel.ErrorCodes;
import com.kinghool.smodel.IModel;
import com.kinghool.smodel.IXmlModel;
import com.kinghool.smodel.io.IModelChannel;
import com.kinghool.smodel.utils.JDomUtils;

/**
 * 
 * @Author Allen Deng(dengtailin@gmail.com) 
 */
public class XmlChannel implements IModelChannel {
    private String rootId;
	private final IDocumentProvider docProvider;
	private final Writer writer;
	
	public XmlChannel(IDocumentProvider docProvider, Writer writer) {
		this.docProvider = docProvider;
		this.writer = writer;
	}
   
	public XmlChannel(InputStream inputStream, OutputStream outputStream) {
		this.docProvider = new InputStreamDocumentProvider(inputStream);
		this.writer = new OutputStreamWriter(outputStream);
	}

	/**
	 * for sub class only
	 */
	protected XmlChannel() {
		this.docProvider = null;
		this.writer = null;
	}
   
	public void flushModel(IModel model) {
		if (model instanceof IXmlModel) {
			Element element = ((IXmlModel)model).populate();
			Document document = element.getDocument();
			if (document == null) {
				document = new Document();
				document.setRootElement(element);
			}
			if (((IXmlModel)model).getDocType() != null) {
				document.setDocType(((IXmlModel)model).getDocType());
			}
		  
		    Writer writer = getWriter();
			try {
				JDomUtils.writeXml(document, writer);
			} catch (IOException e) {
				throw new ErrorCodeRuntimeException(ErrorCodes.SMODEL_003.cloneWithArgs("xml"), e);
			}
			
			afterLoad(writer);
		}
	}
 
	public void loadModel(IModel model) {
		if (model instanceof IXmlModel) {		    
			Document document;
			try {
				document = getDocumentProvider().getDocument();
				((IXmlModel)model).refresh(document.getRootElement());	
			} catch (Exception e) {
				throw new ErrorCodeRuntimeException(ErrorCodes.SMODEL_004.cloneWithArgs("xml"), e);
			}
		}
	}
	
	protected void afterLoad(Writer writer) {
	}
	
	protected IDocumentProvider getDocumentProvider() {
		return docProvider;
	}
	
	protected Writer getWriter() {
		return writer;
	}
  
	public Object getMappedObject() {
		throw new UnsupportedOperationException("use XmlModelStringChannel instead.");
	} 
	 
	public void setMappedObject(Object xml) {
		throw new UnsupportedOperationException("use XmlModelStringChannel instead.");
	}

	public String getRootId() {
		return rootId;
	}

	public void setRootId(String rootId) {
		this.rootId = rootId;
	}

}
